package com.peak.spring.boot.tools;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.SSLContext;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.peak.spring.boot.core.exception.Exceptions;

public class HttpClients {

	private static final Logger log = LoggerFactory.getLogger(HttpClients.class);

	public static String get(String url, Map<String, String> param) {
		CloseableHttpClient httpclient = null;
		String response = null;
		if (url.indexOf("?") == -1) {
			url += "?";
		}
		url += Converts.toUrlParam(param);
		log.info("GET请求URL = \n" + url);
		try {
			httpclient = buildHttpClient();
			HttpUriRequest httpget = RequestBuilder.get(url).build();
			response = httpclient.execute(httpget, new ResponseHandler<String>() {

				@Override
				public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {
					int status = response.getStatusLine().getStatusCode();
					log.debug("响应状态码 = " + status);
					if (status >= 200 && status < 300) {
						HttpEntity entity = response.getEntity();
						return entity != null ? EntityUtils.toString(entity, Encodes.DEFAULT_URL_ENCODING) : null;
					} else {
						throw new ClientProtocolException("Unexpected response status: " + status);
					}
				}
			});
			log.debug("GET响应内容=" + response);
		} catch (IOException e) {
			log.error("发生网络异常", e);
			Exceptions.unchecked(e);
		} finally {
			try {
				httpclient.close();
			} catch (IOException e) {
				Exceptions.unchecked(e);
			}
		}

		return response;
	}

	public static String getFile(String url, String localPath) {
		CloseableHttpClient httpclient = null;
		String response = null;
		log.info("GET请求URL = \n" + url);
		try {
			httpclient = buildHttpClient();
			HttpUriRequest httpget = RequestBuilder.get(url).build();
			response = httpclient.execute(httpget, new ResponseHandler<String>() {

				@Override
				public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {
					int status = response.getStatusLine().getStatusCode();
					log.debug("响应状态码 = " + status);
					Header[] headers = response.getAllHeaders();
					String fileName = null;
					for (Header header : headers) {
						if ("Content-disposition".equals(header.getName())) {
							fileName = StringUtils.substringsBetween(header.getValue(), "filename=\"", "\"")[0];
						}
					}
					if (Emptys.isEmpty(fileName)) {
						fileName = Identities.randomBase62(8) + ".jpg";
					}
					String path = localPath + File.separator + fileName;
					if (status >= 200 && status < 300) {
						HttpEntity entity = response.getEntity();
						File img = new File(path);
						log.info("下载文件保存到：{}", path);
						FileUtils.copyInputStreamToFile(entity.getContent(), img);
						return img.getName();
					} else {
						throw new ClientProtocolException("Unexpected response status: " + status);
					}
				}
			});
		} catch (IOException e) {
			log.error("发生网络异常", e);
			Exceptions.unchecked(e);
		} finally {
			try {
				httpclient.close();
			} catch (IOException e) {
				Exceptions.unchecked(e);
			}
		}

		return response;
	}

	public static String post(String url, Map<String, String> param) {
		return post(url, param, null);
	}

	public static String post(String url, Map<String, String> param, Map<String, String> headers) {
		CloseableHttpClient httpclient = null;
		String response = null;
		log.info("Post请求URL = \n" + url);
		try {
			httpclient = buildHttpClient();
			List<NameValuePair> nvps = Lists.newArrayList();
			if (Emptys.isNotEmpty(param)) {
				for (Entry<String, String> entry : param.entrySet()) {
					nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
				}
			}
			
			RequestBuilder builder = RequestBuilder.post().setUri(url)
					.setEntity(new UrlEncodedFormEntity(nvps, Encodes.DEFAULT_URL_ENCODING));

			if (Emptys.isNotEmpty(headers)) {
				for (Entry<String, String> entry : headers.entrySet()) {
					builder.addHeader(entry.getKey(), entry.getValue());
				}
			}

			HttpUriRequest httppost = builder.build();
			response = httpclient.execute(httppost, new ResponseHandler<String>() {

				@Override
				public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {
					int status = response.getStatusLine().getStatusCode();
					log.debug("响应状态码 = " + status);
					if (status >= 200 && status < 300) {
						HttpEntity entity = response.getEntity();
						return entity != null ? EntityUtils.toString(entity, Encodes.DEFAULT_URL_ENCODING) : null;
					} else {
						throw new ClientProtocolException("Unexpected response status: " + status);
					}
				}
			});
			log.debug("GET响应内容=" + response);
		} catch (IOException e) {
			log.error("发生网络异常", e);
			Exceptions.unchecked(e);
		} finally {
			try {
				httpclient.close();
			} catch (IOException e) {
				Exceptions.unchecked(e);
			}
		}

		return response;
	}

	private static CloseableHttpClient buildHttpClient() {
		// 支持https传输
		SSLContext sslcontext = SSLContexts.createSystemDefault();
		Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
				.register("http", PlainConnectionSocketFactory.INSTANCE)
				.register("https", new SSLConnectionSocketFactory(sslcontext)).build();
		PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
		// 3分钟超时
		RequestConfig defaultRequestConfig = RequestConfig.custom()
				.setSocketTimeout(180000)
				.setConnectTimeout(180000)
				.setConnectionRequestTimeout(180000)
				.build();
		CloseableHttpClient httpclient = org.apache.http.impl.client.HttpClients.custom()
				.setConnectionManager(connManager)
				.setDefaultRequestConfig(defaultRequestConfig)
				.build();
		return httpclient;
	}
}
